package constants

import (
	"strings"
	"time"
)

// HeaderField .
type HeaderField struct {
	HeaderKey   string
	HeaderField string
}

// const .
const (
	KeyBaseRequest                  = "IBaseRequest"
	KeyExtraRequest                 = "ExtraRequest"
	HTTP_HEADER_KEY_LANGUAGE        = "language"
	HTTP_HEADER_KEY_ACCEPT_LANGUAGE = "Accept-Language"
	RequestAppName                  = "App_name"
)

// var .
var (
	PresetHeaders = []HeaderField{
		HeaderField{HeaderKey: "App_version", HeaderField: "BsAppVersion"},
		HeaderField{HeaderKey: "Os_type", HeaderField: "BsOsType"},
		HeaderField{HeaderKey: "Os_version", HeaderField: "BsOsVersion"},
		HeaderField{HeaderKey: "Phone_model", HeaderField: "BsPhoneModel"},
		HeaderField{HeaderKey: "Model_type", HeaderField: "ModelType"},
		HeaderField{HeaderKey: "Openudid", HeaderField: "BsOpenUdid"},
		HeaderField{HeaderKey: "Country", HeaderField: "BsCountry"},
		HeaderField{HeaderKey: "Language", HeaderField: "BsLanguage"},
		HeaderField{HeaderKey: "X-Request-Id", HeaderField: "BsRequestID"},
		HeaderField{HeaderKey: "X-Auth-Token", HeaderField: "BsAuthToken"},
		HeaderField{HeaderKey: "Timezone", HeaderField: "BsTimezone"},
		HeaderField{HeaderKey: "Time_offset", HeaderField: "BsTimeOffset"},
		HeaderField{HeaderKey: "Os_type", HeaderField: "BsOsType"},
		HeaderField{HeaderKey: "User-Agent", HeaderField: "BsUserAgent"},
		HeaderField{HeaderKey: "X-Real-Ip", HeaderField: "BsRemoteAddr"},
		HeaderField{HeaderKey: "X-Forwarded-For", HeaderField: "BsForwardedFor"},
		HeaderField{HeaderKey: "App_name", HeaderField: "BsAppName"},
		HeaderField{HeaderKey: "Gtoken", HeaderField: "Gtoken"},
	}
)

// IBaseRequest .
type IBaseRequest interface {
	GetOsType() string
	GetOsVersion() string
	GetModelType() string
	GetAppVersion() string
	GetPhoneModel() string
	GetCountry() string
	GetLanguage() string
	GetTimezone() string
	GetOpenUdid() string
	GetUID() string
	GetNetType() string
	GetChid() string
	GetMnc() string
	GetMcc() string
	GetRequestID() string
	GetAuthToken() string
	GetTimeOffset() string
	GetUserAgent() string
	GetRemoteAddr() string
	GetForwardedFor() string
	CheckAndGetModelTypeV2() string
	GetAppName() string
	GetGToken() string
}

// BaseRequest 请求基本字段，从Header读取
type BaseRequest struct {
	BsOsType       string `json:"-" swaggo:"false,系统类型"`
	BsOsVersion    string `json:"-" swaggo:"false,系统版本"`
	BsAppVersion   string `json:"-" swaggo:"false,应用版本"`
	BsPhoneModel   string `json:"-" swaggo:"false,手机型号"`
	ModelType      string `json:"-" swaggo:"false,设备类型"`
	BsCountry      string `json:"-" swaggo:"false,国家代码"`
	BsLanguage     string `json:"-" swaggo:"false,语言代码"`
	BsTimezone     string `json:"-" swaggo:"false,时区"`
	BsOpenUdid     string `json:"-" swaggo:"false,设备唯一标识"`
	BsUID          string `json:"-" swaggo:"false,用户id"`
	BsNetType      string `json:"-" swaggo:"false,网络类型"`
	BsChid         string `json:"-" swaggo:"false,渠道id"`
	BsMnc          string `json:"-" swaggo:"false,移动网络码"`
	BsMcc          string `json:"-" swaggo:"false,移动国家码"`
	BsRequestID    string `json:"-" swaggo:"false,请求ID"`
	BsAuthToken    string `json:"-" swaggo:"false,令牌"`
	BsTimeOffset   string `json:"-" swaggo:"false,与UTC时差(单位秒)"`
	BsUserAgent    string `json:"-" swaggo:"false,用户代理"`
	BsRemoteAddr   string `json:"-" swaggo:"false,远程地址"`
	BsForwardedFor string `json:"-" swaggo:"false,中转地址"`
	BsAppName      string `json:"-" swaggo:"false,请求app名称"`
	Gtoken         string `json:"-" swaggo:"false,gtoken值为user_id的md5值"`
}

func (r *BaseRequest) GetAppName() string {
	//如果是eufy_care那么返回，否则返回空，兼容旧版本
	if r.BsAppName == EufyCare {
		return r.BsAppName
	}
	return ""
}

// GetOsType .
func (r *BaseRequest) GetOsType() string {
	return r.BsOsType
}

// GetModelType
func (r *BaseRequest) GetModelType() string {

	//如果为空，判断是否是web或者是app
	if r.ModelType != "" {
		if r.ModelType != WEB_MODEL_TYPE && r.ModelType != PHONE_MODEL_TYPE && r.ModelType != PAD_MODEL_TYPE && r.ModelType != IPOD_MODEL_TYPE && r.ModelType != PC_MODEL_TYPE {
			return ""
		}
		return r.ModelType
	}
	r.ModelType = WEB_MODEL_TYPE
	if strings.ToLower(r.GetOsType()) == ANDROID_TYPE || strings.ToUpper(r.GetOsType()) == OS_TYPE {
		r.ModelType = PHONE_MODEL_TYPE
	}

	return r.ModelType
}

// 新版本接口必须带上请求头
func (r *BaseRequest) CheckAndGetModelTypeV2() string {
	modelTypeList := []string{WEB_MODEL_TYPE, PHONE_MODEL_TYPE, PAD_MODEL_TYPE, IPOD_MODEL_TYPE, PC_MODEL_TYPE}
	if r.ModelType == "" {
		return ""
	}
	for _, modelType := range modelTypeList {
		if modelType == r.ModelType {
			return r.ModelType
		}
	}
	return ""
}

// GetOsVersion .
func (r *BaseRequest) GetOsVersion() string {
	return r.BsOsVersion
}

// GetAppVersion .
func (r *BaseRequest) GetAppVersion() string {
	return r.BsAppVersion
}

// GetPhoneModel .
func (r *BaseRequest) GetPhoneModel() string {
	return r.BsPhoneModel
}

// GetCountry .
func (r *BaseRequest) GetCountry() string {
	return r.BsCountry
}

// GetLanguage .
func (r *BaseRequest) GetLanguage() string {
	return r.BsLanguage
}

// GetTimezone .
func (r *BaseRequest) GetTimezone() string {
	return r.BsTimezone
}

// GetOpenUdid .
func (r *BaseRequest) GetOpenUdid() string {
	return r.BsOpenUdid
}

// GetUID .
func (r *BaseRequest) GetUID() string {
	return r.BsUID
}

// GetNetType .
func (r *BaseRequest) GetNetType() string {
	return r.BsNetType
}

// GetChid .
func (r *BaseRequest) GetChid() string {
	return r.BsChid
}

// GetMnc .
func (r *BaseRequest) GetMnc() string {
	return r.BsMnc
}

// GetMcc .
func (r *BaseRequest) GetMcc() string {
	return r.BsMcc
}

// GetRequestID .
func (r *BaseRequest) GetRequestID() string {
	return r.BsRequestID
}

// GetAuthToken .
func (r *BaseRequest) GetAuthToken() string {
	return r.BsAuthToken
}

// GetTimeOffset .
func (r *BaseRequest) GetTimeOffset() string {
	return r.BsTimeOffset
}

// GetUserAgent .
func (r *BaseRequest) GetUserAgent() string {
	return r.BsUserAgent
}

// GetRemoteAddr .
func (r *BaseRequest) GetRemoteAddr() string {
	return r.BsRemoteAddr
}

// GetForwardedFor .
func (r *BaseRequest) GetForwardedFor() string {
	return r.BsForwardedFor
}

// GetGToken .
func (r *BaseRequest) GetGToken() string {
	return r.Gtoken
}

// ExtraRequest 扩展字段
type ExtraRequest struct {
	ExTag            string      `json:"-" swaggo:"false,标签值"`
	ExPath           string      `json:"-" swaggo:"false,标签值"`
	ExUserID         string      `json:"-" swaggo:"false,用户ID"`
	ExActionID       string      `json:"-" swaggo:"false,操作ID"`
	ExActionSubID    string      `json:"-" swaggo:"false,子操作ID"`
	ExStationSn      string      `json:"-" swaggo:"false,基站SN"`
	ExDeviceSn       string      `json:"-" swaggo:"false,设备SN"`
	ExErrMsg         string      `json:"-" swaggo:"false,错误消息"`
	ExParams         string      `json:"-" swaggo:"false,请求参数"`
	ExMessage        string      `json:"-" swaggo:"false,结果消息"`
	ExLatency        int64       `json:"-" swaggo:"false,延时时长"`
	ExCode           int         `json:"-" swaggo:"false,结果代码"`
	ExParamsObject   interface{} `json:"-" swaggo:"false,请求参数对象"`
	ExResponseString string      `json:"-" swaggo:"false,响应参数"`
}

// ApiRequest api请求数据结构
type ApiRequest struct {
	ArTimestamp string `json:"@timestamp,omitempty" swaggo:"false,时间"`
	ArService   string `json:"service,omitempty" swaggo:"false,服务名"`
	ArLevel     string `json:"level,omitempty" swaggo:"false,级别"`
	//ArArea  string `json:"area,omitempty" swaggo:"false,位置"`
	//ArHostname  string `json:"hostname,omitempty" swaggo:"false,机器名"`

	ArOsType     string `json:"os_type,omitempty" swaggo:"false,系统类型"`
	ArOsVersion  string `json:"os_version,omitempty" swaggo:"false,系统版本"`
	ArAppVersion string `json:"app_version,omitempty" swaggo:"false,应用版本"`
	ArPhoneModel string `json:"phone_model,omitempty" swaggo:"false,手机型号"`
	ArCountry    string `json:"country,omitempty" swaggo:"false,国家代码"`
	ArLanguage   string `json:"language,omitempty" swaggo:"false,语言代码"`
	ArTimezone   string `json:"time_zone,omitempty" swaggo:"false,时区"`
	ArOpenUdid   string `json:"open_udid,omitempty" swaggo:"false,设备唯一标识"`
	ArUID        string `json:"uid,omitempty" swaggo:"false,用户id"`
	ArNetType    string `json:"net_type,omitempty" swaggo:"false,网络类型"`
	ArChid       string `json:"chid,omitempty" swaggo:"false,渠道id"`
	ArMnc        string `json:"mnc,omitempty" swaggo:"false,移动网络码"`
	ArMcc        string `json:"mcc,omitempty" swaggo:"false,移动国家码"`
	ArRequestID  string `json:"request_id,omitempty" swaggo:"false,请求ID"`
	ArToken      string `json:"token,omitempty" swaggo:"false,令牌"`
	ArTimeOffset string `json:"time_offset,omitempty" swaggo:"false,与UTC时差(单位秒)"`
	ArUserAgent  string `json:"user_agent,omitempty" swaggo:"false,用户代理"`
	ArRemote     string `json:"remote,omitempty" swaggo:"false,远程地址"`
	ArForwarded  string `json:"forwarded,omitempty" swaggo:"false,中转地址"`
	ArModelType  string `json:"model_type,omitempty"`
	ArAppName    string `json:"app_name,omitempty"`
	ArGToken     string `json:"gtoken,omitempty"`

	ArTag         string `json:"tag,omitempty" swaggo:"false,标签值"`
	ArPath        string `json:"path,omitempty" swaggo:"false,路径"`
	ArUserID      string `json:"user_id,omitempty" swaggo:"false,用户ID"`
	ArActionID    string `json:"action_id,omitempty" swaggo:"false,操作ID"`
	ArActionSubID string `json:"action_sub_id,omitempty" swaggo:"false,子操作ID"`
	ArStationSn   string `json:"station_sn,omitempty" swaggo:"false,基站SN"`
	ArDeviceSn    string `json:"device_sn,omitempty" swaggo:"false,设备SN"`
	ArErrMsg      string `json:"error_message,omitempty" swaggo:"false,错误消息"`
	ArParams      string `json:"params,omitempty" swaggo:"false,请求参数"`
	ArResponse    string `json:"response,omitempty" swaggo:"false,响应结果"`
	ArMessage     string `json:"message,omitempty" swaggo:"false,结果消息"`
	ArLatency     int64  `json:"latency,omitempty" swaggo:"false,延时时长"`
	ArCode        int    `json:"code" swaggo:"false,结果代码"`
	//ArParamsObject      interface{} `json:"params_object,omitempty" swaggo:"false,请求参数对象"`
}

// BuildApiRequest .
func BuildApiRequest(bs IBaseRequest, ex *ExtraRequest) (ar ApiRequest) {
	ar.ArLevel = "DEBUG"
	ar.ArTimestamp = time.Now().UTC().Format(time.RFC3339)
	ar.ArService = ServerName()
	if bs != nil {
		ar.ArOsType = bs.GetOsType()
		ar.ArOsVersion = bs.GetOsVersion()
		ar.ArAppVersion = bs.GetAppVersion()
		ar.ArPhoneModel = bs.GetPhoneModel()
		ar.ArCountry = bs.GetCountry()
		ar.ArLanguage = bs.GetLanguage()
		ar.ArTimezone = bs.GetTimezone()
		ar.ArOpenUdid = bs.GetOpenUdid()
		ar.ArUID = bs.GetUID()
		ar.ArNetType = bs.GetNetType()
		ar.ArChid = bs.GetChid()
		ar.ArMnc = bs.GetMnc()
		ar.ArMcc = bs.GetMcc()
		ar.ArRequestID = bs.GetRequestID()
		ar.ArToken = bs.GetAuthToken()
		ar.ArTimeOffset = bs.GetTimeOffset()
		ar.ArUserAgent = bs.GetUserAgent()
		ar.ArRemote = bs.GetRemoteAddr()
		ar.ArForwarded = bs.GetForwardedFor()
		ar.ArModelType = bs.CheckAndGetModelTypeV2()
		ar.ArAppName = bs.GetAppName()
		ar.ArGToken = bs.GetGToken()
	}
	if ex != nil {
		ar.ArTag = ex.ExTag
		ar.ArPath = ex.ExPath
		ar.ArUserID = ex.ExUserID
		ar.ArActionID = ex.ExActionID
		ar.ArActionSubID = ex.ExActionSubID
		ar.ArStationSn = ex.ExStationSn
		ar.ArDeviceSn = ex.ExDeviceSn
		ar.ArErrMsg = ex.ExErrMsg
		ar.ArParams = ex.ExParams
		// 注意：不能使用对象方式写ES，不同接口的字段不一样，类型可能也不一样，导致写ES会失败
		//ar.ArParamsObject = ex.ExParamsObject
		//if ar.ArParamsObject == nil && len(ex.ExParams) > 0 {
		//	ar.ArParams = ex.ExParams
		//}
		ar.ArMessage = ex.ExMessage
		ar.ArLatency = ex.ExLatency
		ar.ArCode = ex.ExCode
		ar.ArResponse = ex.ExResponseString
	}
	return
}
